package org.jmh.gift.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.jmh.gift.contants.SysConstants;
import org.jmh.gift.domain.TenantType;
import org.jmh.gift.dto.TenantTypeDelayDoubleDelDTO;
import org.jmh.gift.mapper.TenantTypeMapper;
import org.jmh.gift.service.ITenantTypeService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lingfeng
 * @since 2024-07-18
 */
@Service
public class TenantTypeServiceImpl extends ServiceImpl<TenantTypeMapper, TenantType> implements ITenantTypeService {
    private static final String TENANT_TYPE_REDIS_KEY = "tenant_type_redis_key";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Override
    public List<TenantType> selectList(Wrapper<TenantType> wrapper) {
        Object obj = redisTemplate.opsForValue().get(TENANT_TYPE_REDIS_KEY);
        if(Objects.nonNull(obj)){
            return (List<TenantType>)obj;
        }
        List<TenantType> tenantTypes = super.selectList(wrapper);
        redisTemplate.opsForValue().set(TENANT_TYPE_REDIS_KEY,tenantTypes);
        return tenantTypes;
    }

    //异步延迟双删
    private void asyncDelayDoubleDel() {
        // 2 第一次删除缓存
        redisTemplate.delete(TENANT_TYPE_REDIS_KEY);

        // 单开一个线程,睡眠一会儿以后,做第二次缓存删除
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 3 睡眠一会儿,第二次删除缓存
                try {
                    Thread.sleep(3000);
                    redisTemplate.delete(TENANT_TYPE_REDIS_KEY);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    //同步延迟双删
    private void syncDelayDoubleDel() {
        // 2 第一次删除缓存
        redisTemplate.delete(TENANT_TYPE_REDIS_KEY);

        // 3 睡眠一会儿,第二次删除缓存
        try {
            Thread.sleep(3000);
            redisTemplate.delete(TENANT_TYPE_REDIS_KEY);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public boolean insert(TenantType entity) {
        // 封装message对象
        TenantTypeDelayDoubleDelDTO dto = new TenantTypeDelayDoubleDelDTO(entity, 1);
        return sendTransactionMessage(dto);
    }

    @Override
    public boolean update(TenantType entity, Wrapper<TenantType> wrapper) {
        // 封装message对象
        TenantTypeDelayDoubleDelDTO dto = new TenantTypeDelayDoubleDelDTO(entity, 2);
        return sendTransactionMessage(dto);
    }

    @Override
    public boolean deleteById(Serializable id) {
        TenantType tenantType = new TenantType();
        tenantType.setId((Long)id);
        TenantTypeDelayDoubleDelDTO dto = new TenantTypeDelayDoubleDelDTO(tenantType, 3);
        return sendTransactionMessage(dto);
    }

    @Override
    public void delayDoubleDelExecuteLocalTransaction(TenantTypeDelayDoubleDelDTO dto) {
        Integer operateType = dto.getOperateType();
        TenantType type = dto.getType();
        Boolean flag = false;
        // 1 操作数据库
        switch (operateType){
            case 1: // 新增
                flag = super.insert(type);
                break;
            case 2: // 修改
                flag = super.updateById(type);
                break;
            case 3: // 删除
                flag = super.deleteById(type.getId());
                break;
        }

        // 2 第一次删除缓存
        redisTemplate.delete(TENANT_TYPE_REDIS_KEY);
        System.out.println("==========第一次缓存删除===========");
    }

    @Override
    public Boolean delayDoubleDelCheckLocalTransaction(TenantTypeDelayDoubleDelDTO dto) {
        Integer operateType = dto.getOperateType();
        TenantType type = dto.getType();
        Boolean flag = false;
        switch (operateType){
            case 1: // 新增
                int count = super.selectCount(new EntityWrapper<TenantType>().eq("name", type.getName()));
                flag = count > 0;
                break;
            case 2: // 修改
                TenantType tenantType = super.selectById(type.getId());
                flag = type.equals(tenantType);
                break;
            case 3: // 删除
                tenantType = super.selectById(type.getId());
                flag = Objects.isNull(tenantType);
                break;
        }
        return flag;
    }
    private boolean sendTransactionMessage(TenantTypeDelayDoubleDelDTO dto) {
        Message<TenantTypeDelayDoubleDelDTO> message = MessageBuilder.withPayload(dto).build();

        //发送rocketmq事务消息
        TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(
                SysConstants.TENANT_TYPE_DELAY_DOUBLE_DEL_TX_PRODUCER_GROUP,
                SysConstants.TENANT_TYPE_DELAY_DOUBLE_DEL_TX_TOPIC + ":" + SysConstants.TENANT_TYPE_DELAY_DOUBLE_DEL_TX_TAG,
                message, null
        );
        System.out.println(sendResult);
        if (sendResult.getSendStatus() != SendStatus.SEND_OK ||
                sendResult.getLocalTransactionState() != LocalTransactionState.COMMIT_MESSAGE) {
            return false;
        }
        return true;
    }
}
